/*
 * Copyright (C) <2009> 
 *
 * <Rishi B Agrawal> <Sneha Hendre>
 * <rishi.b.agrawal@gmail.com> <sneha.hendre@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify it 
 * under the terms of the GNU General Public License as published by the 
 * Free Software Foundation, either version 3 of the License, or (at your 
 * option) any later version->
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE->  See the
 * GNU General Public License for more details.
 *  
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <libxml/parser.h>
#include <libxml/xmlmemory.h>
#include "../include/ohsm.h"
#include "ohsm_u.h"

int 
get_relops (char *temp_relop) {

	if (!strcmp (temp_relop, "LT"))  return LT; 
	else if (!strcmp (temp_relop, "GT"))  return GT;
	else if (!strcmp (temp_relop, "EQ"))  return EQ;
	else if (!strcmp (temp_relop, "NEQ")) return NEQ;
	else if (!strcmp (temp_relop, "LE"))  return LE; 
	else if (!strcmp (temp_relop, "GE"))  return GE; 
	else return -1;
}

int 
parse_when (xmlDocPtr doc, xmlNodePtr cur) {

	xmlChar *key;
	int retval, no;
	long long temp;
	
	cur = cur->xmlChildrenNode;
	cur = cur->next;
	while (cur != NULL) {
		
		if ((!xmlStrcmp (cur->name, (const xmlChar *) "FSIZE"))) {
			key = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
			relocpol->policy[relocpol->pidx].reloc_criteria_bitmap |= FSIZE;	  
			temp = validate_id_long (key);
			
			if (temp == -1) {
				no =  (int) xmlGetLineNo (cur);
				printf("\nOHSM: [%d] : wrong value in <FSIZE> tag ", no);
				return temp;
			}
		
			relocpol->policy[relocpol->pidx].values[0] = temp;
			xmlFree (key);
			cur = cur->next;	
			
			if ((!xmlStrcmp (cur->name, (const xmlChar *) "REL"))){
				key = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
				retval = (int) get_relops ((char *) key);
				
				if (retval == -1) {
					no = (int) xmlGetLineNo (cur);
					printf("\nOHSM: [%d] : wrong value in <REL> tag", no);
					return retval;
				}
				relocpol->policy[relocpol->pidx].rel_ops[0] = retval;
				xmlFree (key);
			}
		}	
		cur = cur->next->next;
		
		if ((!xmlStrcmp (cur->name, (const xmlChar *) "FMA"))){
			key = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
			relocpol->policy[relocpol->pidx].reloc_criteria_bitmap |= FMA;	  
			temp = validate_id_long (key);
			
			if (temp == -1) {
				no = (int) xmlGetLineNo (cur);
				printf("\nOHSM: [%d] : wrong value in <FMA> tag ", no);
				return temp;
			}
			
			relocpol->policy[relocpol->pidx].values[1] = temp;
			xmlFree (key);
			cur = cur->next;
			
			if ((!xmlStrcmp (cur->name, (const xmlChar *) "REL"))){
				key = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
				retval = (int) get_relops ((char *) key);
				
				if (retval == -1) {
					no = (int) xmlGetLineNo (cur);
					printf("\nOHSM: [%d] : wrong value in <REL> tag", no);
					return retval;
				}
				relocpol->policy[relocpol->pidx].rel_ops[1] = retval;
				xmlFree (key);
			}
		}

		cur = cur->next->next;
		
		if ((!xmlStrcmp (cur->name, (const xmlChar *) "FAA"))){
			key = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
			relocpol->policy[relocpol->pidx].reloc_criteria_bitmap |= FAA;	  
			temp = validate_id_long(key);
			
			if (temp == -1) {
				no = (int) xmlGetLineNo (cur);
				printf("\nOHSM: [%d] : wrong value in <FAA> tag ", no);
				return temp;
			}
			
			relocpol->policy[relocpol->pidx].values[2] = temp;
			xmlFree (key);
			cur = cur->next;
		
			if ((!xmlStrcmp (cur->name, (const xmlChar *) "REL"))){
				key = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
				retval = (int) get_relops ((char *) key);
				
				if (retval == -1) {
					no = (int) xmlGetLineNo (cur);
					printf("\nOHSM: [%d] : wrong value in <REL> tag", no);
					return retval;
				}
				relocpol->policy[relocpol->pidx].rel_ops[2] = retval;
				xmlFree (key);
			}
		}	
		cur = cur->next->next;
		
		if ((!xmlStrcmp (cur->name, (const xmlChar *) "FIOT"))){
			key = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
			relocpol->policy[relocpol->pidx].reloc_criteria_bitmap |= FIOT;	  
			temp = validate_id_long (key);
			
			if (temp == -1) {
				no = (int) xmlGetLineNo (cur);
				printf("\nOHSM: [%d] : wrong value in <FIOT> tag ", no);
				return temp;
			}
			relocpol->policy[relocpol->pidx].values[3] = temp;
			xmlFree (key);
			cur = cur->next;
		
			if ((!xmlStrcmp (cur->name, (const xmlChar *) "REL"))){
				key = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
				retval = (int) get_relops ((char *) key);
				
				if (retval == -1) {
					no = (int) xmlGetLineNo (cur);
					printf("\nOHSM: [%d] : wrong value in <REL> tag", no);
					return retval;
				}
				relocpol->policy[relocpol->pidx].rel_ops[3] = retval;
				xmlFree (key);
			}
		}	
		cur = cur->next->next;
		
		if ((!xmlStrcmp (cur->name, (const xmlChar *) "FAT"))){
			key = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
			relocpol->policy[relocpol->pidx].reloc_criteria_bitmap |= FAT;	  
			temp = validate_id_long(key);
			
			if (temp == -1) {
				no = (int) xmlGetLineNo (cur);
				printf("\nOHSM: [%d] : wrong value in <FAT> tag ", no);
				return temp;
			}
			relocpol->policy[relocpol->pidx].values[4] = temp;
			xmlFree (key);
			cur = cur->next;
		
			if ((!xmlStrcmp (cur->name, (const xmlChar *) "REL"))){
				key = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
				retval = (int) get_relops ((char *) key);
				
				if (retval == -1) {
					no = (int) xmlGetLineNo (cur);
					printf("\nOHSM: [%d] : wrong value in <REL> tag", no);
					return retval;
				}
				relocpol->policy[relocpol->pidx].rel_ops[4] = retval;
				xmlFree (key);
			}
			
		}	
			
		cur = cur->next->next;
	}
	return 0;			//sucessfull
}


int 
parse_single_rule (xmlDocPtr doc, xmlNodePtr cur) {

	xmlChar *key;
	int temp, no;
	
	cur = cur->xmlChildrenNode;
	cur = cur->next;

	relocpol->policy[relocpol->pidx].reloc_criteria_bitmap = 0;
	
	while (cur != NULL){
		
		if ((!xmlStrcmp (cur->name, (const xmlChar *) "FROM"))){
			key = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
			temp = validate_key(key);
			
			if (temp == -1 || temp == 0) {
				printf("\nOHSM: invalid tier value in tier tag\n");				
				return -1;
			}
			relocpol->policy[relocpol->pidx].src_tier = temp;
			xmlFree (key);
		}
		cur = cur->next->next;
		
		if ((!xmlStrcmp (cur->name, (const xmlChar *) "TO"))){
			key = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
			temp = validate_key(key);
			
			if (temp == -1 || temp == 0) {
				no = (int) xmlGetLineNo (cur);
				printf("\nOHSM: [%d] : invalid tier value in tier tag\n", no);				
				return -1;	
			}
			relocpol->policy[relocpol->pidx].dest_tier = temp;
			xmlFree (key);
		}
		cur = cur->next->next;
		
		if (!cur) {
			return 0;
		}
		
		if ((!xmlStrcmp (cur->name, (const xmlChar *) "WHEN"))){
			
			relocpol->policy[relocpol->pidx].rel_ops[0] = 0;
			relocpol->policy[relocpol->pidx].rel_ops[1] = 0;
			relocpol->policy[relocpol->pidx].rel_ops[2] = 0;
			relocpol->policy[relocpol->pidx].rel_ops[3] = 0;
			relocpol->policy[relocpol->pidx].rel_ops[4] = 0;

			relocpol->policy[relocpol->pidx].values[0] = 0;
			relocpol->policy[relocpol->pidx].values[1] = 0;
			relocpol->policy[relocpol->pidx].values[2] = 0;
			relocpol->policy[relocpol->pidx].values[3] = 0;
			relocpol->policy[relocpol->pidx].values[4] = 0;
			
			parse_when(doc, cur);
			
		} 
		cur = cur->next->next;
	}
	return 0;			//success ful
}



int 
parse_doc_rel (char *docname) {
	
	xmlDocPtr doc;
	xmlNodePtr cur;
	int cnt_policies = 0;
	int temp, no;
	xmlChar *key;

	doc = xmlParseFile (docname);
	xmlLineNumbersDefault(1);
	
	if (!doc) {
		printf ("\nOHSM: Document not parsed successfully");
		xmlFreeDoc (doc);
		return -1;
	}
	cur = xmlDocGetRootElement (doc);
	
	if (!cur) {
		printf ("\nOHSM: Empty document");
		xmlFreeDoc (doc);
		return -1;
	}
	
	if (xmlStrcmp (cur->name, (const xmlChar *) "RELOC_POLICY")){
		printf ("\nOHSM: Invalid document Root element not equal to create...%s", docname);
	    xmlFreeDoc (doc);
		return -1;
	}

	cur = cur->xmlChildrenNode;
	cur = cur->next;

		if ((!xmlStrcmp (cur->name, (xmlChar *) "NR_RULES"))){
			key = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
			temp = validate_key(key);
			
			if (temp == -1) {
				no = (int) xmlGetLineNo (cur);
				printf("\nOHSM: [%d] : wrong value in <NR_RULES> tag", no);
				printf("\nOHSM: [%d] : fatal : cannot proceed further", no);
				return temp;
			}
			relocpol->cnt_policies = temp;
			cur = cur->next->next;

			while (cur != NULL) {
				
				if ((!xmlStrcmp (cur->name, (const xmlChar *) "RULE"))) {
					cnt_policies++;
					parse_single_rule (doc, cur);
					relocpol->pidx++;
				}
				cur = cur->next->next;
			}
		}


	if (cnt_policies != relocpol->cnt_policies) {
		no = (int) xmlGetLineNo (cur);
		printf("\nOHSM: [%d] : wrong value in <NR_RULE> number of rules different then entered RULES", no);
		return -1;
	}

	xmlFreeDoc (doc);
	return 0;
}

int 
ohsm_get_relocation_policy (char *filename) {
	
	int retval = 0;
	char cmd[80]= "";
	
	sprintf(cmd,"xmllint --valid --noout %s", filename);	
	retval = system (cmd);
	
	if (retval) { 
		printf("\nOHSM: error in tags of %s \nrefer DTD file", filename);
		return -1;
	}	
	
	retval = parse_doc_rel (filename);	
	
	if (retval) {
		printf ("\nOHSM: Retval has value %d", retval);
		return retval;
	}
	
	return 0;
}

